﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;

namespace Ausy.Silverlight.Survey.Common.Extensions.Commands
{
    /// <summary>
    /// Cette classe représente la Propriété attachée à la Frame pour la Navigation
    /// </summary>
    public class Navigated
    {
        #region Command AttachedProperty

        /// <summary>
        /// Cette méthode permet de récupérer la commande associée
        /// </summary>
        /// <param name="obj">Commande associée</param>
        /// <returns>Commande associée</returns>
        public static ICommand GetCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(CommandProperty);
        }

        /// <summary>
        /// Cette méthode permet de récupérer la commande associée
        /// </summary>
        /// <param name="obj">Commande associée</param>
        /// <param name="value">Commande affectée</param>
        public static void SetCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(CommandProperty, value);
        } 
        
        /// <summary>
        /// Propriété Command attachée 
        /// Using a DependencyProperty as the backing store for Command.  This enables animation, styling, binding, etc...
        /// </summary>
        public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(Navigated), new PropertyMetadata(OnSetCommandCallback));

        /// <summary>
        /// Cette méthode permet de gérer le changement de l'affectation de la nouvelle commande
        /// </summary>
        /// <param name="dependencyObject">Objet attaché</param>
        /// <param name="e">Argument contenant la nouvelle commande</param>
        private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            //Retrieve the ToggleButton control
            Frame element = dependencyObject as Frame;

            if (element != null)
            {
                NavigatedCommand NavigatedCommand = GetOrCreateBehavior(element);

                //Set the Command to be the ICommand
                NavigatedCommand.Command = e.NewValue as ICommand;
            }
        }

        #endregion

        #region CommandParameter AttachedProperty

        /// <summary>
        /// Cette méthode permet de récupérer le booléen des paramètres
        /// </summary>
        /// <param name="obj">Objet attaché</param>
        /// <returns>Uri associé</returns>
        public static Uri GetCommandParameter(DependencyObject obj)
        {
            return (Uri)obj.GetValue(CommandParameterProperty);
        }

        /// <summary>
        /// Cette méthode permet d'affecter un booléen des paramètres
        /// </summary>
        /// <param name="obj">Objet attaché</param>
        /// <param name="value">Booléen affecté</param>
        public static void SetCommandParameter(DependencyObject obj, Uri value)
        {
            obj.SetValue(CommandParameterProperty, value);
        }
        
        /// <summary>
        /// Parametres de commande
        /// Using a DependencyProperty as the backing store for CommandParameter.  This enables animation, styling, binding, etc...
        /// </summary>
        public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached("CommandParameter", typeof(Uri), typeof(NavigatedCommand), new PropertyMetadata(OnSetCommandParameterCallback));

        /// <summary>
        /// Cette méthode permet de gérer le changement d'affectation des paramètres de commande
        /// </summary>
        /// <param name="dependencyObject">Objet attaché</param>
        /// <param name="e">Argument contenant les nouveaux paramètres</param>
        private static void OnSetCommandParameterCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            Frame control = dependencyObject as Frame;

            if (control != null)
            {
                NavigatedCommand NavigatedCommandBehavior = GetOrCreateBehavior(control);
                NavigatedCommandBehavior.CommandParameter = e.NewValue;
            }
        }

        #endregion

        #region GetOrCreateBehavior Method

        /// <summary>
        /// Cette méthode permet de vérifier qu'il est possible d'affecter une commande de ce type
        /// </summary>
        /// <param name="element">Element de Frame</param>
        /// <returns>Commande vérifiée</returns>
        private static NavigatedCommand GetOrCreateBehavior(Frame element)
        {
            //Naivgation if the bevavior doesn't exist then create it
            //Attach the bevahior
            NavigatedCommand NavigatedCommand = element.GetValue(NavigatedCommandBehaviorProperty) as NavigatedCommand;
            if (NavigatedCommand == null)
            {
                NavigatedCommand = new NavigatedCommand(element);
                element.SetValue(NavigatedCommandBehaviorProperty, NavigatedCommand);
            }

            return NavigatedCommand;
        } 

        #endregion

        #region NavigatedCommandBehavior AttachedProperty

        /// <summary>
        /// Cette méthode permet de récupére la commande vérifiée
        /// </summary>
        /// <param name="obj">Objet attaché</param>
        /// <returns>Commande vérifiée</returns>
        public static NavigatedCommand GetNavigatedCommandBehavior(DependencyObject obj)
        {
            return (NavigatedCommand)obj.GetValue(NavigatedCommandBehaviorProperty);
        }

        /// <summary>
        /// Affection d'une commande vérifiée à l'objet attaché
        /// </summary>
        /// <param name="obj">Objet attaché</param>
        /// <param name="value">Commande vérifiée</param>
        public static void SetNavigatedCommandBehavior(DependencyObject obj, NavigatedCommand value)
        {
            obj.SetValue(NavigatedCommandBehaviorProperty, value);
        }

        /// <summary>
        /// Propriété Command vérifiée attachée 
        /// Using a DependencyProperty as the backing store for NavigatedCommandBehaviorProperty.  This enables animation, styling, binding, etc...
        /// </summary>
        private static readonly DependencyProperty NavigatedCommandBehaviorProperty = DependencyProperty.RegisterAttached("NavigatedCommandBehavior", typeof(NavigatedCommand), typeof(Navigated), null);

        #endregion
    }
}
